using System;
using System.Threading;
using Xunit;

namespace muduoDotNet.Tests
{
    public class LoggerTest
    {
        [Fact]
        public void TestLoggerLevels()
        {
            var originalOutput = Console.Out;
            var stringWriter = new System.IO.StringWriter();
            
            try
            {
                Logger.SetOutput(stringWriter);
                Logger.SetLogLevel(LogLevel.Info);
                
                Logger.Debug("This should not appear");
                Logger.Info("This should appear");
                Logger.Warning("This should appear");
                Logger.Error("This should appear");
                Logger.Fatal("This should appear");
                
                var output = stringWriter.ToString();
                
                Assert.DoesNotContain("This should not appear", output);
                Assert.Contains("This should appear", output);
                Assert.Contains("[INFO   ]", output);
                Assert.Contains("[WARNING]", output);
                Assert.Contains("[ERROR  ]", output);
                Assert.Contains("[FATAL  ]", output);
            }
            finally
            {
                Logger.SetOutput(originalOutput);
            }
        }

        [Fact]
        public void TestLoggerWithException()
        {
            var originalOutput = Console.Out;
            var stringWriter = new System.IO.StringWriter();
            
            try
            {
                Logger.SetOutput(stringWriter);
                Logger.SetLogLevel(LogLevel.Error);
                
                var exception = new InvalidOperationException("Test exception");
                Logger.Error("Error occurred", exception);
                
                var output = stringWriter.ToString();
                
                Assert.Contains("Error occurred", output);
                Assert.Contains("Test exception", output);
                Assert.Contains("[ERROR  ]", output);
            }
            finally
            {
                Logger.SetOutput(originalOutput);
            }
        }

        [Fact]
        public void TestLoggerThreadSafety()
        {
            var originalOutput = Console.Out;
            var stringWriter = new System.IO.StringWriter();
            
            try
            {
                // 确保测试隔离，等待之前的异步操作完成
                Thread.Sleep(100);
                
                Logger.SetOutput(stringWriter);
                Logger.SetLogLevel(LogLevel.Info);
                
                const int threadCount = 5;  // 减少线程数提高稳定性
                const int messagesPerThread = 50;  // 减少消息数提高稳定性
                var threads = new Thread[threadCount];
                var countdown = new CountdownEvent(threadCount);
                var messageCounter = 0;
                
                for (int i = 0; i < threadCount; i++)
                {
                    int threadId = i;
                    threads[i] = new Thread(() =>
                    {
                        try
                        {
                            for (int j = 0; j < messagesPerThread; j++)
                            {
                                Logger.Info($"Thread {threadId} Message {j}");
                                Interlocked.Increment(ref messageCounter);
                            }
                        }
                        finally
                        {
                            countdown.Signal();
                        }
                    });
                }
                
                foreach (var thread in threads)
                {
                    thread.Start();
                }
                
                // 等待所有线程完成，最多等待10秒
                Assert.True(countdown.Wait(10000), "线程未在预期时间内完成");
                
                // 确保所有输出都已刷新
                Thread.Sleep(100);
                
                var output = stringWriter.ToString();
                var lines = output.Split('\n', StringSplitOptions.RemoveEmptyEntries);
                
                // 验证消息计数器和实际行数
                var expectedCount = threadCount * messagesPerThread;
                Assert.Equal(expectedCount, messageCounter);
                
                // 允许一定的容差，因为可能存在格式差异
                Assert.True(Math.Abs(lines.Length - expectedCount) <= 30, 
                    $"期望大约 {expectedCount} 行日志，但得到 {lines.Length} 行");
            }
            finally
            {
                Logger.SetOutput(originalOutput);
            }
        }
    }
}